from django.shortcuts import render
from django import http
from django.views import View
import json
from django_redis import get_redis_connection

from meiduo_mall.utils.log import logger_out
from meiduo_mall.utils.response_code import RETCODE
from goods.models import SKU
from meiduo_mall.utils import meiduo_json
from . import constants


class CartsView (View):
    # 添加购物车
    def post(self, request):
        # 接受
        # loads：解码，字符串解码成字典
        # dumps: 编码，将字典编码成字符串
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        sku_count = json_dict.get('count')
        selected =json_dict.get('selected')
        # 判断
        if not all([sku_id, sku_count]):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数不完整！'})
        # 如果加入购物车的数量大于5或者小于1,则需要提示
        if sku_count > 5:
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '购买数量大于5'})
        if sku_count < 1:
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '购买数量小于1'})
        # 判断购买的数量大于sku的库存
        sku_stock = SKU.objects.get(id=int(sku_id))
        if sku_count > sku_stock.stock:
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '该产品的库存不够！'})

        # 处理
        # 如果用户登录，则添加到购物车的商品保存到redis
        if request.user.is_authenticated:
            # 登录状态，将购物车存入redis
            redis_cli = get_redis_connection('carts')
            # 向redis存商品编号，数量
            # 向hash中存放hash：键是：用户名id  值是：sku_id：商品库存id   sku_count:需要购买的数量
            # redis_cli.hset('cart%d' % request.user.id, sku_id, sku_count)
            redis_cli.hincrby('cart%d' % request.user.id, sku_id, sku_count)
            # # 添加集合：user_id, sku_id
            if selected:
                redis_cli.sadd('selected%d' % request.user.id, sku_id)

            # 根据是否添加到购物车进行筛选
            # if selected:
            #     # 添加集合：user_id, sku_id
            #     redis_cli.sadd('selected%d' % request.user.id, sku_id)
            # else:
            #     redis_cli.srem('selected%d' % request.user.id, sku_id)
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK！'})
        else:
            # 如果用户没有登录，则添加到cookie中
            # 读取购物车的数据
            carts_str = request.COOKIES.get('carts')
            # 如果读取为空，则需要添加，否则解密成字典
            if carts_str:
                carts_dict = meiduo_json.loads(carts_str)
            else:
                carts_dict = {}
            carts_dict[sku_id] = {
                'count': sku_count,
                'selected': True,
                'sku_id': sku_id
            }
            json_str = meiduo_json.dumps(carts_dict)
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK！'})
            response.set_cookie('carts', json_str, max_age=constants.CARTS_EXPIRES)
            return response

    # 展示购物车
    def get(self, request):
        # 获取当前的用户
        user = request.user
        # 判断当前的用户是否登录
        # 购物车存放在redis里面

        # cookie中存储的数据:
        #  carts_dict[sku_id] = {
        #            'count': sku_count,
        #           'selected': True,
        #           'sku_id': sku_id
        #       }
        # 思路
        if user.is_authenticated:
            redis_cli = get_redis_connection('carts')
            # 读取字典: 键:cart_user.id        值是: {键:sku_id:值:count}
            # 读取集合, selected_user.id  值是: sku_id
            hash_content = redis_cli.hgetall('cart%d' % user.id)
            # 获取一个集合，(sku_id)
            set_content = redis_cli.smembers('selected%d' % user.id)
            carts_dict = {}
            for sku_id, count in hash_content.items():
                carts_dict[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in set_content,
                }
        # 购物车存放在cookie中
        else:
            dict = request.COOKIES.get('carts')
            if dict:
                # 购物篮数据不为空
                carts_dict = meiduo_json.loads(dict)
            else:
                # 购物篮数据为空
                carts_dict = {}
        # 构造返回的数据格式
        # carts_dict[sku_id] = {
        #     'count': sku_count,
        #     'selected': True,
        #     'sku_id': sku_id
        # }
        # 构造购物车渲染数据
        sku_ids = carts_dict.keys()
        skus = SKU.objects.filter(id__in=sku_ids)
        cart_sku = []
        for sku in skus:
            cart_sku.append({
                'id': sku.id,
                'name': sku.name,
                'count': carts_dict.get(sku.id).get('count'),
                'selected': str(carts_dict[sku.id]['selected']),
                'default_image': sku.default_image.url,
                'price': str(sku.price),
                'amount': str(sku.price * int(carts_dict.get(sku.id).get('count')))
            })
        context = {
            'cart_skus': cart_sku,
        }
        return render(request, 'cart.html', context)

    # 修改购物车
    def put(self, request):
        # 接受
        json_dict = json.loads(request.body.decode())
        sku_id = int(json_dict.get('sku_id'))
        count = json_dict.get('count')
        selected = json_dict.get('selected')

        # 验证
        if not all([sku_id, count]):
            return http.HttpResponseForbidden('参数不完整')
        try:
            count = int(count)
        except Exception as e:
            logger_out.warning(e)
            return http.HttpResponseForbidden('参数count有误')
        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            logger_out.warning(e)
            return http.HttpResponseForbidden('没有当前用户')
        if selected:
            if not isinstance(selected, bool):
                return http.HttpResponseForbidden('selected参数有问题。')

        cart_sku = {
            'id': sku_id,
            'count': count,
            'selected': str(selected),
            'name': sku.name,
            'default_image': sku.default_image.url,
            'price': str(sku.price),
            'amount': str(sku.price * count),
        }

        # 处理
        user = request.user
        if user.is_authenticated:
            # 登录ok，从redis中读取数据
            redis_cli = get_redis_connection('carts')
            redis_pipe = redis_cli.pipeline()
            # 保存数据到redis中
            redis_pipe.hset('cart%d' % user.id, sku.id, count)
            if selected:
                redis_pipe.sadd('selected%d' % user.id, sku.id)
            else:
                redis_pipe.srem('selected%d' % user.id, sku.id)
            redis_pipe.execute()
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK！', 'cart_sku': cart_sku})

        else:
            # 未登录，从cookie中读取数据
            carts_str = request.COOKIES.get('carts')
            if carts_str:
                carts_dict = meiduo_json.loads(carts_str)
            else:
                carts_dict = {}
            carts_dict[sku_id] = {
                'count': count,
                'selected': selected,
                'sku_id': sku_id,
            }
            # 将修改后的数据保存到cookies中去
            carts_str_cookies = meiduo_json.dumps(carts_dict)
            # 返回的数据类型
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK！', 'cart_sku': cart_sku})
            response.set_cookie('carts', carts_str_cookies, max_age=constants.CARTS_EXPIRES)
            return response

    # 删除购物车
    def delete(self, request):
        user = request.user
        sku_id = int(json.loads(request.body.decode()).get('sku_id'))
        if user.is_authenticated:
            # 登录ok，从redis中读取数据
            redis_cli = get_redis_connection('carts')
            redis_pipe = redis_cli.pipeline()
            # 保存数据到redis中
            redis_pipe.hdel('cart%d' % user.id, sku_id)
            redis_pipe.srem('selected%d' % user.id, sku_id)
            redis_pipe.execute()
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除已经成功！'})
        else:
            # 未登录，从cookie中读取数据
            carts_str = request.COOKIES.get('carts')
            if carts_str:
                carts_dict = meiduo_json.loads(carts_str)
            else:
                carts_dict = {}
            if sku_id in carts_dict:
                del carts_dict[sku_id]
            # 将修改后的数据保存到cookies中去
            carts_str_cookies = meiduo_json.dumps(carts_dict)
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除成功！！'})
            response.set_cookie('carts', carts_str_cookies, max_age=constants.CARTS_EXPIRES)
            return response


# 购物车全选
class CartSelectionView (View):
    def put(self, request):
        # 获取参数
        dict1 = json.loads(request.body.decode())
        selected = dict1.get('selected', True)
        # 判断
        if not isinstance(selected, bool):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数类型错误'})
        response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
        # 判断用户是否登录
        if request.user.is_authenticated:
            redis_cli = get_redis_connection('carts')
            redis_keys = redis_cli.hkeys('cart%d' % request.user.id)
            if selected:
                redis_cli.sadd('selected%d' % request.user.id, *redis_keys)
            else:
                redis_cli.srem('selected%d' % request.user.id, *redis_keys)
        else:
            carts_str = request.COOKIES.get('carts')
            cart_dict = meiduo_json.loads(carts_str)
            for sku_id in cart_dict:
                cart_dict[sku_id]['selected'] = selected
            cart_sec_str = meiduo_json.dumps(cart_dict)
            response.set_cookie('carts', cart_sec_str, max_age=constants.CARTS_EXPIRES)
        return response


# 购物车简单展示
class CartsSimpleView (View):
    def get(self, request):
        # 获取当前的用户
        user = request.user
        # 判断当前的用户是否登录
        # 购物车存放在redis里面
        if user.is_authenticated:
            redis_cli = get_redis_connection('carts')
            # 读取字典: 键:cart_user.id        值是: {键:sku_id:值:count}
            # 读取集合, selected_user.id  值是: sku_id
            hash_content = redis_cli.hgetall('cart%d' % user.id)
            # 获取一个集合，(sku_id)
            set_content = redis_cli.smembers('selected%d' % user.id)
            carts_dict = {}
            for sku_id, count in hash_content.items():
                carts_dict[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in set_content,
                }
        # 购物车存放在cookie中
        else:
            dict = request.COOKIES.get('carts')
            if dict:
                # 购物篮数据不为空
                carts_dict = meiduo_json.loads(dict)
            else:
                # 购物篮数据为空
                carts_dict = {}
        # 构造返回的数据格式
        # carts_dict[sku_id] = {
        #     'count': sku_count,
        #     'selected': True,
        #     'sku_id': sku_id
        # }
        # 构造购物车渲染数据
        sku_ids = carts_dict.keys()
        skus = SKU.objects.filter(id__in=sku_ids)
        cart_skus = []
        for sku in skus:
            cart_skus.append({
                'id': sku.id,
                'name': sku.name,
                'count': carts_dict.get(sku.id).get('count'),
                'default_image_url': sku.default_image.url,
            })

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok', 'cart_skus': cart_skus})
